﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SPC
{
    class SpcXbarS : ISPC
    {
        double usl = 0;
        double lsl = 0;
        double[] xbar;
        double[] s;

        double xdbar;
        double sbar;
        double sigmaC;
        double sigmaP;

        int groupCapacity;

        public SpcXbarS(double[][] x, double usl, double lsl)
        {
            this.usl = usl;
            this.lsl = lsl;
            groupCapacity = x[0].Length;
            xbar = new double[x.Length];
            s = new double[x.Length];
            for (int i = 0; i < x.Length; i++)
            {
                xbar[i] = x[i].Average();
                s[i] = StdDevition(x[i]);
            }
            xdbar = xbar.Average();
            sbar = s.Average();
            sigmaC = sbar / CtrlChartFactor.Factor(groupCapacity, "C4");
            sigmaP = CaculateSigmaP(x);
        }
        /// <summary>
        /// 计算子组标准差
        /// </summary>
        /// <param name="groupData"></param>
        /// <returns></returns>
        private double StdDevition(double[] groupData)
        {
            double xBar = groupData.Average();
            double sum = 0;
            for (int i = 0; i < groupData.Length; i++)
            {
                sum += Math.Pow((groupData[i] - xBar), 2);
            }
            return Math.Sqrt(sum / (groupData.Length - 1));
        }
        private double CaculateSigmaP(double[][] x)
        {
            double sum = 0;
            for (int i = 0; i < x.Length; i++)
            {
                for (int j = 0; j < x[i].Length; j++)
                {
                    sum += Math.Pow(x[i][j] - xdbar, 2);
                }
            }
            return Math.Sqrt(sum / (groupCapacity * x.Length - 1));
        }
        public double LSL
        { set { lsl = value; } }
        public double USL
        { set { usl = value; } }
        public double CP()
        {
            double cp = 0;
            if (usl != 0 && lsl != 0)
            { cp = (usl - lsl) / (6 * sigmaC); }
            else if (usl != 0)
            { cp = (usl - xdbar) / (3 * sigmaC); }
            else
            { cp = (xdbar - lsl) / (3 * sigmaC); }
            return cp;
        }

        public double CPK()
        {
            double cpu = 0, cpl = 0;
            if (usl != 0) { cpu = (usl - xdbar) / (3 * sigmaC); }
            if (lsl != 0) { cpl = (xdbar - lsl) / (3 * sigmaC); }
            double[] cps = { cpu, cpl };
            return cps.Min();
        }

        public SCtrlDiagram[] GetCtrlDiagrams()
        {
            SCtrlDiagram[] diags = new SCtrlDiagram[2];
            double lcl = xdbar - CtrlChartFactor.Factor(groupCapacity, "A3") * sbar;
            diags[0] = new SCtrlDiagram()
            {
                diagramName = DiagramName.xbar,
                cl = xdbar,
                lcl = lcl > 0 ? lcl : 0,
                ucl = xdbar + CtrlChartFactor.Factor(groupCapacity, "A3") * sbar,
                points = xbar
            };
            diags[1] = new SCtrlDiagram()
            {
                diagramName = DiagramName.S,
                cl = sbar,
                lcl = sbar * CtrlChartFactor.Factor(groupCapacity, "B3"),
                ucl = sbar * CtrlChartFactor.Factor(groupCapacity, "B4"),
                points = s
            };
            return diags;
        }

        public double PP()
        {
            double pp = 0;
            if (usl != 0 && lsl != 0)
            { pp = (usl - lsl) / (6 * sigmaP); }
            else if (usl != 0)
            { pp = (usl - xdbar) / (3 * sigmaP); }
            else
            { pp = (xdbar - lsl) / (3 * sigmaP); }
            return pp;
        }

        public double PPK()
        {
            double ppu = 0, ppl = 0;
            if (usl != 0) { ppu = (usl - xdbar) / (3 * sigmaP); }
            if (lsl != 0) { ppl = (xdbar - lsl) / (3 * sigmaP); }
            double[] pps = { ppu, ppl };
            return pps.Min();
        }
    }
}
